home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / a_utils / _archvrs / unix / shar.lha / shar / findsrc.c < prev    next >
C/C++ Source or Header  |  1987-12-03  |  7KB  |  290 lines

  1. /*
  2. **  FINDSRC
  3. **  Walk directories, trying to find source files.
  4. **
  5. **  Options:
  6. **    -d [yn]        Set default answer to yes or no
  7. **    -.        Do .cshrc, .profile, etc.
  8. **    -o file        Redirect stdout
  9. **    -R        Do RCS and SCCS files and directories
  10. **    -S        Do SCCS and RCS files and directories
  11. **    -v        Verbose, include those that were rejected
  12. */
  13. #include "shar.h"
  14. RCS("$Header: findsrc.c,v 1.18 87/03/18 14:03:03 rs Exp $")
  15.  
  16.  
  17. /*
  18. **  How many levels to walk down?
  19. */
  20. #define MAX_LEVELS    6
  21.  
  22.  
  23. /*
  24. **  Global variables.
  25. */
  26. int     DoDOTFILES;            /* Do .newsrc and friends?    */
  27. int     DoRCS;                /* Do RCS and SCCS files?    */
  28. int     Default;            /* Default answer from user    */
  29. int     Verbose;            /* List rejected files, too?    */
  30. char     Dname[] = "/tmp/findDXXXXXX";    /* Filename of directory list    */
  31. char     Fname[] = "/tmp/findFXXXXXX";    /* Filename of file list    */
  32. FILE    *Dfile;                /* List of directories found    */
  33. FILE    *Ffile;                /* List of files found        */
  34. FILE    *DEVTTY;            /* The tty, if in filter mode    */
  35.  
  36.  
  37. /*
  38. **  Signal handler.  Clean up and die.
  39. */
  40. static
  41. Catch(s)
  42.     int         s;
  43. {
  44.     int         e;
  45.  
  46.     e = errno;
  47.     (void)unlink(Dname);
  48.     (void)unlink(Fname);
  49.     fprintf(stderr, "Got signal %d, %s.\n", s, Ermsg(e));
  50.     exit(1);
  51. }
  52.  
  53.  
  54. /*
  55. **  Given a filename, apply heuristics to see if we want it.
  56. */
  57. static int
  58. Wanted(Name)
  59.     register char    *Name;
  60. {
  61.     register FILE    *F;
  62.     register char    *s;
  63.     register char    *p;
  64.     register char    *d;
  65.     char         buff[BUFSIZ];
  66.  
  67.     /* Get down to brass tacks. */
  68.     s = (p = RDX(Name, '/')) ? p + 1 : Name;
  69.  
  70.     /* Only do directories other than . and .. and regular files. */
  71.     if ((Ftype(Name) != F_DIR && Ftype(Name) != F_FILE)
  72.      || EQ(s, ".") || EQ(s, ".."))
  73.     return(FALSE);
  74.  
  75.     /* Common cruft we never want. */
  76.     if (EQ(s, "foo") || EQ(s, "core") || EQ(s, "tags") || EQ(s, "lint"))
  77.     return(FALSE);
  78.  
  79.     /* Disregard stuff with bogus suffixes. */
  80.     d = RDX(s, '.');
  81.     if ((p = d)
  82.      && (EQ(++p, "out") || EQ(p, "orig") || EQ(p, "rej") || EQ(p, "BAK")
  83.       || EQ(p, "CKP") || EQ(p, "old") || EQ(p, "o")))
  84.     return(FALSE);
  85.  
  86.     /* Want .cshrc, .newsrc, etc.? */
  87.     if (*s == '.' && isalpha(s[1]))
  88.     return(DoDOTFILES);
  89.  
  90.     /* RCS or SCCS file or directory? */
  91.     if (EQ(s, "RCS")
  92.      || ((p = RDX(s, ',')) && *++p == 'v' && *++p == '\0')
  93.      || EQ(s, "SCCS") || (s[0] == 's' && s[1] == '.'))
  94.     return(DoRCS);
  95.  
  96.     /* Mlisp (yes to .ml, no to .mo)? */
  97.     if ((p = d) && *++p == 'm' && p[2] == '\0')
  98.     return(*++p = 'l');
  99.  
  100.     /* C source or manpage? */
  101.     if ((p = d) && (*++p == 'c' || *p == 'h' || isdigit(*p))
  102.      && *++p == '\0')
  103.     return(TRUE);
  104.  
  105.     /* Make control file? */
  106.     if ((*s == 'M' || *s == 'm') && EQ(s + 1, "akefile"))
  107.     return(TRUE);
  108.  
  109.     /* Convert to lowercase, and see if it's a README or MANIFEST. */
  110.     for (p = strcpy(buff, s); *p; p++)
  111.     if (isupper(*p))
  112.         *p = tolower(*p);
  113.     if (EQ(buff, "readme") || EQ(buff, "read_me") || EQ(buff, "read-me")
  114.      || EQ(buff, "manifest"))
  115.     return(TRUE);
  116.  
  117.     /* If we have a default, give it back. */
  118.     if (Default)
  119.     return(Default == 'y');
  120.  
  121. #ifdef    CAN_POPEN
  122.     /* See what file(1) has to say; if it says executable, punt. */
  123.     (void)sprintf(buff, "exec file '%s'", Name);
  124.     if (F = popen(buff, "r")) {
  125.     (void)fgets(buff, sizeof buff, F);
  126.     (void)pclose(F);
  127.     for (p = buff; p = IDX(p, 'e'); p++)
  128.         if (PREFIX(p, "executable"))
  129.         return(FALSE);
  130.     (void)fputs(buff, stderr);
  131.     }
  132. #endif    /* CAN_POPEN */
  133.  
  134.     /* Add it? */
  135.     while (TRUE) {
  136.     if (DEVTTY == NULL)
  137.         DEVTTY = fopen(THE_TTY, "r");
  138.     fprintf(stderr, "Add this one (y or n)[y]?  ");
  139.     (void)fflush(stderr);
  140.     if (fgets(buff, sizeof buff, DEVTTY) == NULL
  141.      || buff[0] == '\n' || buff[0] == 'y' || buff[0] == 'Y')
  142.         break;
  143.     if (buff[0] == 'n' || buff[0] == 'N')
  144.         return(FALSE);
  145.     if (buff[0] == '!' )
  146.         (void)system(&buff[1]);
  147.     fprintf(stderr, "--------------------\n%s:  ", Name);
  148.     clearerr(DEVTTY);
  149.     }
  150.     return(TRUE);
  151. }
  152.  
  153.  
  154. /*
  155. **  Quick and dirty recursive routine to walk down directory tree.
  156. **  Could be made more general, but why bother?
  157. */
  158. static void
  159. Process(p, level)
  160.     register char     *p;
  161.     register int      level;
  162. {
  163.     register char     *q;
  164.     DIR             *Dp;
  165.     struct direct     *E;
  166.     char          buff[BUFSIZ];
  167.  
  168.     if (!GetStat(p))
  169.     fprintf(stderr, "Can't walk down %s, %s.\n", Ermsg(errno));
  170.     else {
  171.     /* Skip leading ./ which find(1), e.g., likes to put out. */
  172.     if (p[0] == '.' && p[1] == '/')
  173.         p += 2;
  174.  
  175.     if (Wanted(p))
  176.         fprintf(Ftype(p) == F_FILE ? Ffile : Dfile, "%s\n", p);
  177.     else if (Verbose)
  178.         fprintf(Ftype(p) == F_FILE ? Ffile : Dfile, "PUNTED %s\n", p);
  179.  
  180.     if (Ftype(p) == F_DIR)
  181.         if (++level == MAX_LEVELS)
  182.         fprintf(stderr, "Won't walk down %s -- more than %d levels.\n",
  183.             p, level);
  184.         else if (Dp = opendir(p)) {
  185.         q = buff + strlen(strcpy(buff, p));
  186.         for (*q++ = '/'; E = readdir(Dp); )
  187.             if (!EQ(E->d_name, ".") && !EQ(E->d_name, "..")) {
  188.             (void)strcpy(q, E->d_name);
  189.             Process(buff, level);
  190.             }
  191.         (void)closedir(Dp);
  192.         }
  193.         else
  194.         fprintf(stderr, "Can't open directory %s, %s.\n",
  195.             p, Ermsg(errno));
  196.     }
  197. }
  198.  
  199.  
  200. main(ac, av)
  201.     register int     ac;
  202.     register char    *av[];
  203. {
  204.     register char    *p;
  205.     register int     i;
  206.     register int     Oops;
  207.     char         buff[BUFSIZ];
  208.  
  209.     /* Parse JCL. */
  210.     for (Oops = 0; (i = getopt(ac, av, ".d:o:RSv")) != EOF; )
  211.     switch (i) {
  212.         default:
  213.         Oops++;
  214.         break;
  215.         case '.':
  216.         DoDOTFILES++;
  217.         break;
  218.         case 'd':
  219.         switch (optarg[0]) {
  220.             default:
  221.             Oops++;
  222.             case 'y':
  223.             case 'n':
  224.             break;
  225.             case 'Y':
  226.             Default = 'y';
  227.             break;
  228.             case 'N':
  229.             Default = 'n';
  230.             break;
  231.         }
  232.         break;
  233.         case 'o':
  234.         if (freopen(optarg, "w", stdout) == NULL) {
  235.             fprintf(stderr, "Can't open %s for output, %s.\n",
  236.                 optarg, Ermsg(errno));
  237.             exit(1);
  238.         }
  239.         case 'R':
  240.         case 'S':
  241.         DoRCS++;
  242.         break;
  243.         case 'v':
  244.         Verbose++;
  245.         break;
  246.     }
  247.     if (Oops) {
  248.     fprintf(stderr, "Usage: findsrc [-d{yn}] [-.] [-{RS}] [-v] files...\n");
  249.     exit(1);
  250.     }
  251.     av += optind;
  252.  
  253.     /* Set signal catcher, open temp files. */
  254.     SetSigs(TRUE, Catch);
  255.     Dfile = fopen(mktemp(Dname), "w");
  256.     Ffile = fopen(mktemp(Fname), "w");
  257.  
  258.     /* Read list of files, determine their status. */
  259.     if (*av)
  260.     for (DEVTTY = stdin; *av; av++)
  261.         Process(*av, 0);
  262.     else
  263.     while (fgets(buff, sizeof buff, stdin)) {
  264.         if (p = IDX(buff, '\n'))
  265.         *p = '\0';
  266.         else
  267.         fprintf(stderr, "Warning, line too long:\n\t%s\n", buff);
  268.         Process(buff, 0);
  269.     }
  270.  
  271.     /* First print directories. */
  272.     if (freopen(Dname, "r", Dfile)) {
  273.     while (fgets(buff, sizeof buff, Dfile))
  274.         (void)fputs(buff, stdout);
  275.     (void)fclose(Dfile);
  276.     }
  277.  
  278.     /* Now print regular files. */
  279.     if (freopen(Fname, "r", Ffile)) {
  280.     while (fgets(buff, sizeof buff, Ffile))
  281.         (void)fputs(buff, stdout);
  282.     (void)fclose(Ffile);
  283.     }
  284.  
  285.     /* That's all she wrote. */
  286.     (void)unlink(Dname);
  287.     (void)unlink(Fname);
  288.     exit(0);
  289. }
  290.